package cn.texous.web.parsing.book.service.impl.mysql;

import cn.texous.util.commons.exception.BusinessException;
import cn.texous.util.commons.util.CollectionUtils;
import cn.texous.util.commons.util.GsonUtils;
import cn.texous.util.commons.util.StringUtils;
import cn.texous.web.parsing.book.common.constants.AnaResultCode;
import cn.texous.web.parsing.book.config.mysql.AbstractService;
import cn.texous.web.parsing.book.dao.mysql.AnaBookChapterMapper;
import cn.texous.web.parsing.book.manager.RedisManager;
import cn.texous.web.parsing.book.model.dto.AnaSearchChapterDTO;
import cn.texous.web.parsing.book.model.entity.mysql.AnaBookChapter;
import cn.texous.web.parsing.book.model.resp.AnaSearchCatalogResp;
import cn.texous.web.parsing.book.model.resp.AnaSearchChapterResp;
import cn.texous.web.parsing.book.service.api.mysql.AnaBookChapterService;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * insert description here.
 *
 * @author Showa.L
 * @since 2020-03-11 14:20:37
 */
@Service
public class AnaBookChapterServiceImpl
        extends AbstractService<AnaBookChapter> implements AnaBookChapterService {

    @Resource
    private AnaBookChapterMapper anaBookChapterMapper;

    @Override
    public AnaBookChapter findByUnique(String bookCode, String chapterName) {
        return anaBookChapterMapper.findByUnique(bookCode, chapterName);
    }

    @Override
    public List<AnaBookChapter> findByBookCodeCache(String bookCode) {
        if (!StringUtils.isTrimEmpty(bookCode) && RedisManager.existsChapters(bookCode))
            return RedisManager.getBookChapterInfos(bookCode);
        return findByBookCodeAndCache(bookCode);
    }

    @Override
    public AnaSearchCatalogResp findCatalogRespByCache(String bookCode) {
        List<AnaBookChapter> bookChapters = findByBookCodeCache(bookCode);
        if (bookChapters != null) {
            List<AnaSearchChapterDTO> simpleDTOS = bookChapters.stream()
                    .sorted(Comparator.comparing(AnaBookChapter::getNumber))
                    .map(bc -> {
                        AnaSearchChapterDTO dto = new AnaSearchChapterDTO();
                        dto.setCode(bc.getCode());
                        dto.setName(bc.getName());
                        dto.setUrl(bc.getUrl());
                        return dto;
                    }).collect(Collectors.toList());
            AnaSearchCatalogResp resp = new AnaSearchCatalogResp();
            resp.setChapters(simpleDTOS);
            return resp;
        }
        return null;
    }

    @Override
    public AnaSearchChapterResp findByCode(String code) {
        AnaBookChapter bookChapter = anaBookChapterMapper.findByCode(code);
        if (bookChapter == null)
            throw new BusinessException(AnaResultCode.FS_CHAPTER_NOTFIND);
        AnaSearchChapterResp resp = new AnaSearchChapterResp();
        resp.setContent(bookChapter.getContent());
        resp.setName(bookChapter.getName());
        resp.setCode(bookChapter.getCode());
        resp.setAnaBookCode(bookChapter.getAnaBookCode());
        resp.setUrl(bookChapter.getUrl());
        return resp;
    }

    @Override
    public Boolean updateByCode(AnaBookChapter anaBookChapter) {
        Condition condition = new Condition(AnaBookChapter.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("code", anaBookChapter.getCode());
        anaBookChapterMapper.updateByConditionSelective(anaBookChapter, condition);
        return true;
    }

    @Override
    public Integer insertIgnore(List<AnaBookChapter> anaBookChapters) {
        return anaBookChapterMapper.insertIgnore(anaBookChapters);
    }

    @Override
    public AnaBookChapter getFirstChapterByCache(String bookCode) {
        AnaBookChapter chapter = RedisManager.getFirstChapter(bookCode);
        if (chapter == null) {
            chapter = anaBookChapterMapper.getFirstChapter(bookCode);
        }
        return chapter;
    }

    private List<AnaBookChapter> findByBookCodeAndCache(String bookCode) {
        List<AnaBookChapter> bookChapters = anaBookChapterMapper.findByBookCode(bookCode);
        if (CollectionUtils.isEmpty(bookChapters))
            return null;
        Map<String, String> cacheInfos = new HashMap<>();
        bookChapters.forEach(c -> cacheInfos.put(c.getCode(), GsonUtils.toJson(c)));
        RedisManager.cacheBookChapterInfo(cacheInfos, bookCode);
        return bookChapters;
    }
}
